/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.absisgroup.nt;

import com.absisgroup.nsc.utilities.Format;
import com.absisgroup.nsc.utilities.GenericServlet;
import com.absisgroup.nsc.utilities.Util;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.Utilities;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.Date;
import java.util.Properties;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author Hue
 */
public class PhieuBanHangPDF extends GenericServlet {
    private final int TABLE_COLUMNS        = 9;
    private final int DATA_FONT_SIZE       = 11;
    private final int TITLE_FONT_SIZE      = 16;
    private final int COMP_ADDR_FONT_SIZE  = 8;

    @Override
    public int process(final Connection con, final HttpServletRequest request, final HttpServletResponse response) throws Exception {
        BigDecimal orderPK = Util.toBigDecimal(request.getParameter("orderPK"));
        byte[] data = toPDF(con, orderPK);
        response.setHeader("Cache-Control", "no-cache");
        response.setContentType( "application/pdf" );
        response.setContentLength(data.length);
        response.setHeader("Content-Disposition","attachment; filename=\"PhieuBanHang.pdf\"");
        response.getOutputStream().write(data);
        response.getOutputStream().flush();
        
        return DONT_RUN_JSP;
    }
    
    private byte[] toPDF(final Connection con, BigDecimal orderPK) throws Exception {
        Properties texts = Util.getAppTexts(getServletContext());

        String fontName = getServletContext().getRealPath("fonts/times.ttf");
        BaseFont unicode = BaseFont.createFont(fontName, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
        Rectangle pageSize = new Rectangle(Utilities.millimetersToPoints(220f), Utilities.millimetersToPoints(140f));
        final Document document = new Document(pageSize, 15, 15, 1, 1);
        PdfWriter.getInstance(document, baos);
        document.open();
        Font font = new Font(unicode, DATA_FONT_SIZE, Font.NORMAL, BaseColor.BLACK);
        final PdfPTable table = new PdfPTable(3);
        table.setWidthPercentage(100f);
        table.setWidths(new float[] {9f, 55f, 26f});
        table.getDefaultCell().setBorder(0);

        Image logo = Image.getInstance(getServletContext().getRealPath("images/logo.jpg"));
        logo.scaleToFit(56, 56);
        final PdfPCell imageCell = new PdfPCell(logo, false);
        imageCell.setBorder(0);
        table.addCell(imageCell);
        table.addCell(getFactoryAddress(unicode, texts));
        //Mau so 02 vt [
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
        table.addCell(new Paragraph(texts.getProperty("MAU_SO_02_VT"), font));
        //]
        document.add(table);
        //order info [
        OrderEntity entity = getOrderEntity(con, orderPK);
        document.add(getTitle(unicode, texts, entity.getDate(), entity.getOrderNo()));
        PdfPTable orderInfo = getOrderInfo(unicode, texts, entity);
        document.add(orderInfo);
        //]
        //data [
        PdfPTable dataTable = createDataTable(con, orderPK, unicode, texts, entity.getDeposit());
        document.add(dataTable);
        //]
        //footer [
        final PdfPTable footerTable = new PdfPTable(5);
        footerTable.setWidthPercentage(100f);
        footerTable.setWidths(new float[] {20f, 20f, 20f, 20f, 20f});
        footerTable.getDefaultCell().setBorder(0);
        footerTable.getDefaultCell().setColspan(5);
        StringBuilder sb = new StringBuilder();
        sb.append(texts.getProperty("GHI_CHU_MIEN_DOI_LAI"));
        sb.append("                                 ");
        sb.append(texts.getProperty("THOI_GIAN_GIAO_HANG")).append(" ");
        sb.append(getDeliveryDateText(texts, entity.getDelivery()));
        Font italicFont = new Font(unicode, DATA_FONT_SIZE, Font.ITALIC, BaseColor.BLACK);
        footerTable.addCell(new Paragraph(sb.toString(), italicFont));
        Font boldFont = new Font(unicode, DATA_FONT_SIZE, Font.BOLD, BaseColor.BLACK);
        footerTable.getDefaultCell().setColspan(1);
        footerTable.addCell(new Paragraph(texts.getProperty("KHACH_HANG"), boldFont));
        footerTable.addCell(new Paragraph(texts.getProperty("BP_SAN_XUAT"), boldFont));
        footerTable.addCell(new Paragraph(texts.getProperty("TAI_XE"), boldFont));
        footerTable.addCell(new Paragraph(texts.getProperty("NGUOI_THU_TIEN"), boldFont));
        footerTable.addCell(new Paragraph(texts.getProperty("NGUOI_LAP"), boldFont));
        document.add(footerTable);
        //]
        document.close();
        byte[] data = baos.toByteArray();
        baos.close();
        
        return data;
    }
    
    private PdfPTable createDataTable(final Connection con, BigDecimal orderPK, BaseFont unicode, Properties texts, BigDecimal deposit) throws Exception {
        final PdfPTable table = new PdfPTable(TABLE_COLUMNS);
        table.setWidthPercentage(100f);
        table.setWidths(new float[] {5f, 31f, 5f, 5.5f, 5.5f, 8f, 10f, 10f, 19f});
        
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
        table.getDefaultCell().setPaddingTop(3f);
        table.getDefaultCell().setPaddingBottom(3f);

        Font boldFont = new Font(unicode, DATA_FONT_SIZE, Font.BOLD, BaseColor.BLACK);
        table.addCell(new Paragraph("Stt", boldFont));
        table.addCell(new Paragraph(texts.getProperty("TEN_HANG_HOA"), boldFont));
        table.addCell(new Paragraph(texts.getProperty("DVT"), boldFont));
        table.addCell(new Paragraph(texts.getProperty("CHIEU_DAI"), boldFont));
        table.addCell(new Paragraph(texts.getProperty("SO_TAM"), boldFont));
        table.addCell(new Paragraph(texts.getProperty("SO_LUONG"), boldFont));
        table.addCell(new Paragraph(texts.getProperty("DON_GIA"), boldFont));
        table.addCell(new Paragraph(texts.getProperty("THANH_TIEN"), boldFont));
        table.addCell(new Paragraph(texts.getProperty("GHI_CHU"), boldFont));
        
        table.getDefaultCell().setPaddingTop(0);
        Font font = new Font(unicode, DATA_FONT_SIZE, Font.NORMAL, BaseColor.BLACK);
        Format formatNumber = new Format("#,###.##");
        Format formatInteger = new Format("#,###");
        BigDecimal[] totals = addDetailRows(con, orderPK, table, font, formatNumber, formatInteger);
        //tong cong [
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_LEFT);
        table.getDefaultCell().setColspan(4);
        String lpad = "                         ";
        table.addCell(new Paragraph(lpad + texts.getProperty("TONG_CONG"), boldFont));
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
        table.getDefaultCell().setColspan(1);
        table.addCell(new Paragraph(formatNumber.formatNumber(totals[0]), boldFont));
        //
        table.addCell(new Paragraph(formatNumber.formatNumber(totals[1]), boldFont));
        table.addCell(new Paragraph("", boldFont));
        table.addCell(new Paragraph(formatInteger.formatNumber(totals[2]), boldFont));
        table.addCell(new Paragraph("", boldFont));
        //]
        //dat coc [
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_LEFT);
        table.getDefaultCell().setColspan(7);
        table.addCell(new Paragraph(lpad + texts.getProperty("DAT_COC"), boldFont));
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
        table.getDefaultCell().setColspan(1);
        table.addCell(new Paragraph((deposit == null || deposit.longValue() == 0) ? "-" : formatInteger.formatNumber(deposit), boldFont));
        table.addCell(new Paragraph("", boldFont));
        //]
        //con lai [
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_LEFT);
        table.getDefaultCell().setColspan(7);
        table.addCell(new Paragraph(lpad + texts.getProperty("CON_LAI"), boldFont));
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
        table.getDefaultCell().setColspan(1);
        if(deposit == null) {
            table.addCell(new Paragraph(formatInteger.formatNumber(totals[2]), boldFont));
        }
        else {
            table.addCell(new Paragraph(formatInteger.formatNumber(totals[2].subtract(deposit)), boldFont));
        }
        table.addCell(new Paragraph("", boldFont));
        //]
        return table;
    }
    
    private PdfPTable getFactoryAddress(BaseFont unicode, Properties texts) {
        Font arial = new Font(unicode, COMP_ADDR_FONT_SIZE, Font.BOLD, BaseColor.BLACK);
        final PdfPTable table = new PdfPTable(1);
        
        table.getDefaultCell().setBorder(0);
        table.addCell(new Paragraph(texts.getProperty("NHA_MAY_CAN_TON"), arial));
        table.addCell(new Paragraph(texts.getProperty("DIA_CHI_NHA_MAY"), arial));
        table.addCell(new Paragraph("Tel: 0650.3775562 - 3772363        Fax: 0650.3775563", arial));

        final PdfPTable info = new PdfPTable(1);
        info.getDefaultCell().setBorder(0);
        info.addCell(table);

        return info;
    }
    
    private PdfPTable getTitle(BaseFont unicode, Properties texts, Date date, String orderNo) throws DocumentException {
        Font arial = new Font(unicode, DATA_FONT_SIZE, Font.NORMAL, BaseColor.BLACK);
        final PdfPTable table = new PdfPTable(3);
        table.setWidthPercentage(100f);
        table.setWidths(new float[] {20f, 60f, 20f});
        table.getDefaultCell().setBorder(0);

        table.addCell(new Paragraph("", arial));
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
        Font titleFont = new Font(unicode, TITLE_FONT_SIZE, Font.BOLD, BaseColor.BLACK);
        table.addCell(new Paragraph(texts.getProperty("PHIEU_BAN_HANG"), titleFont));
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
        Font redFont = new Font(unicode, DATA_FONT_SIZE, Font.NORMAL, BaseColor.RED);
        table.addCell(new Paragraph(Util.replace(texts.getProperty("SO_PHIEU"), "{0}", orderNo), redFont));
        
        table.addCell(new Paragraph("", arial));
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
        
        String dateText = texts.getProperty("NGAY_THANG_NAM");
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        dateText = Util.replace(dateText, "{0}", String.valueOf(cal.get(Calendar.DATE)));
        dateText = Util.replace(dateText, "{1}", String.valueOf(cal.get(Calendar.MONTH) + 1));
        dateText = Util.replace(dateText, "{2}", String.valueOf(cal.get(Calendar.YEAR)));
        
        table.addCell(new Paragraph(dateText, arial));
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_LEFT);
        table.addCell(new Paragraph("", arial));

        return table;
    }
    
    private String getDeliveryDateText(Properties texts, Date date) {
        if(date == null) {
            return "";
        }
        String dateText = texts.getProperty("NGAY_THANG_NAM_GIO_PHUT");
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        dateText = Util.replace(dateText, "{0}", String.valueOf(cal.get(Calendar.HOUR_OF_DAY)));
        dateText = Util.replace(dateText, "{1}", String.valueOf(cal.get(Calendar.MINUTE)));
        dateText = Util.replace(dateText, "{2}", String.valueOf(cal.get(Calendar.DATE)));
        dateText = Util.replace(dateText, "{3}", String.valueOf(cal.get(Calendar.MONTH) + 1));
        dateText = Util.replace(dateText, "{4}", String.valueOf(cal.get(Calendar.YEAR)));
        return dateText;
    }
    
    private PdfPTable getOrderInfo(BaseFont unicode, Properties texts, OrderEntity entity) throws DocumentException {
        Font arial = new Font(unicode, DATA_FONT_SIZE, Font.BOLD, BaseColor.BLACK);
        final PdfPTable table = new PdfPTable(4);
        table.setWidthPercentage(100f);
        table.setWidths(new float[] {5f, 65f, 8f, 22f});
        table.getDefaultCell().setBorder(0);
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_LEFT);

        table.addCell(new Paragraph(texts.getProperty("NAME") + ":", arial));
        table.addCell(new Paragraph(entity.getCustomer(), arial));
        table.addCell(new Paragraph(texts.getProperty("SDT") + ":", arial));
        table.addCell(new Paragraph(entity.getPhone(), arial));
        table.addCell(new Paragraph(texts.getProperty("DC") + ":", arial));
        table.addCell(new Paragraph(entity.getAddress(), arial));
        table.addCell(new Paragraph("NVBH: ", arial));
        table.addCell(new Paragraph(entity.getSeller(), arial));
        table.setSpacingAfter(5);

        return table;
    }
    
    private void addEmptyRow(final PdfPTable table, final BaseFont unicode) {
        Font font = new Font(unicode, DATA_FONT_SIZE, Font.NORMAL, BaseColor.BLACK);
        font.setColor(BaseColor.WHITE);
        table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_LEFT);
        for(int i=0; i<TABLE_COLUMNS; i++) {
            if(i == TABLE_COLUMNS - 1) {
                table.addCell(new Paragraph(".", font));
            } else {
                table.addCell(new Paragraph("", font));
            }
        }
    }

    private OrderEntity getOrderEntity(Connection con, BigDecimal orderPK) throws SQLException {
        String strQuery = "select ORDER_DATE, ORDER_CUSTOMER, ORDER_ADDRESS, ORDER_DEPOSIT, ORDER_PHONE, ORDER_SELLER, ORDER_NO, ORDER_DELIVERY " +
                          "from ORDERS where ORDER_PK = ?";
        PreparedStatement pStmt = con.prepareStatement(strQuery);
        pStmt.setBigDecimal(1, orderPK);
        ResultSet rs = pStmt.executeQuery();
        OrderEntity entity = new OrderEntity();
        if(rs.next()) {
            entity.setDate(rs.getDate("ORDER_DATE"));
            entity.setCustomer(rs.getString("ORDER_CUSTOMER"));
            entity.setAddress(rs.getString("ORDER_ADDRESS"));
            entity.setDeposit(rs.getBigDecimal("ORDER_DEPOSIT"));
            entity.setPhone(rs.getString("ORDER_PHONE"));
            entity.setSeller(rs.getString("ORDER_SELLER"));
            entity.setOrderNo(rs.getString("ORDER_NO"));
            entity.setDelivery(rs.getTimestamp("ORDER_DELIVERY"));
        }
        pStmt.close();

        return entity;
    }
    
    private BigDecimal[] addDetailRows(Connection con, BigDecimal orderPK, final PdfPTable table, Font font, Format formatNumber, Format formatInteger) throws SQLException {
        BigDecimal[] totals = {new BigDecimal(0), new BigDecimal(0), new BigDecimal(0)};

        String strQuery = "select ORD_DETAILS_STT, PROD_FOR_SELL, ORD_DETAILS_DVT, ORD_DETAILS_CHIEU_DAI, ORD_DETAILS_SO_TAM, ORD_DETAILS_SO_LUONG, ORD_DETAILS_DON_GIA, ORD_DETAILS_GHI_CHU " + 
                          "from ORDERS_DETAILS, PRODUCTS " +
                          "where ORD_DETAILS_PROD_FK = PROD_PK and ORD_DEATAILS_ORDERS_FK = ? " + 
                          "order by ORD_DETAILS_STT";
        PreparedStatement pStmt = con.prepareStatement(strQuery);
        pStmt.setBigDecimal(1, orderPK);
        int iiIndex = 1;
        ResultSet rs = pStmt.executeQuery();
        int iCount = 0;
        while(rs.next()) {
            BigDecimal soLuong = rs.getBigDecimal("ORD_DETAILS_SO_LUONG");
            long donGia = rs.getLong("ORD_DETAILS_DON_GIA");
            
            table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
            table.addCell(new Paragraph(String.valueOf(iiIndex++), font));
            table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_LEFT);
            table.addCell(new Paragraph(rs.getString("PROD_FOR_SELL"), font));
            table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
            table.addCell(new Paragraph(rs.getString("ORD_DETAILS_DVT"), font));
            table.addCell(new Paragraph(formatNumber.formatNumber(rs.getBigDecimal("ORD_DETAILS_CHIEU_DAI")), font));
            BigDecimal soTam = rs.getBigDecimal("ORD_DETAILS_SO_TAM");
            if(soTam != null) {
                totals[0] = totals[0].add(soTam);
            }
            table.addCell(new Paragraph(formatNumber.formatNumber(soTam), font));
            table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
            table.addCell(new Paragraph(formatNumber.formatNumber(soLuong), font));
            table.addCell(new Paragraph(formatInteger.formatNumber(new BigDecimal(donGia)), font));
            if(soLuong == null) {
                table.addCell(new Paragraph("0", font));
            }
            else {
                BigDecimal thanhTien = soLuong.multiply(new BigDecimal(donGia));
                totals[1] = totals[1].add(soLuong);
                totals[2] = totals[2].add(thanhTien);
                table.addCell(new Paragraph(formatInteger.formatNumber(thanhTien), font));
            }
            table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_LEFT);
            table.addCell(new Paragraph(rs.getString("ORD_DETAILS_GHI_CHU"), font));
            iCount++;
        }
        pStmt.close();
        
        //empty rows [
        for(int i=iCount; i<8; i++) {
            addEmptyRow(table, font.getBaseFont());
        }
        //]
        
        return totals;
    }
    
    @Override
    protected boolean useConnection() {
        return true;
    }
}
